#pragma once
#include<iostream>
#include<time.h>
#include<assert.h>
#include<thread>
#include<vector>
#include<Windows.h>
using std::endl;
using std::cout;
static const size_t MAX_Bytes = 128 * 1024;
static const size_t NFREELIST = 208;
static const size_t NPAGES = 129;
static const size_t PAGE_SHIFT = 13;

#ifdef _WIN64
typedef unsigned long long PAGE_ID;
#elif _WIN32
typedef size_t PAGE_ID;
#else
// linux
#endif

inline static void SystemFree(void* ptr)
{
#ifdef _WIN32
	VirtualFree(ptr, 0, MEM_RELEASE);
#else
	// sbrk unmmap等
#endif
}


inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32
	void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
	// linux下brk mmap等
#endif

	if (ptr == nullptr)
		throw std::bad_alloc();

	return ptr;
}


static void*& nextobj(void* obj)
{
	return  *(void**)obj;
}
class freelist
{
public:
	void push(void* obj)  //头插
	{
		assert(obj);
		nextobj(obj) = _freeList;
		_freeList = obj;

		++_size;
	}
	void* pop()
	{
		assert(_freeList);
		void* obj = _freeList;
		_freeList = nextobj(_freeList);
		--_size;
		return obj;
	}
	void pushrange(void* start, void* end,size_t n)
	{
		nextobj(end) = _freeList;
		_freeList = start;
		_size += n;

	}

	void poprange(void*& start, void*& end,size_t n)
	{
		_freeList = start;
		end = start;
		for (int i = 0; i < n; i++)
		{
			end = nextobj(end);
		}
		_freeList = nextobj(end);
		nextobj(end) = nullptr;
		_size -= n;
	}
	bool empty()
	{
		return _freeList == nullptr;
	}

	size_t& maxsize()
	{
		return _maxsize;
	}
private:
	void* _freeList = nullptr;
	size_t _maxsize = 1;
	size_t _size = 0;
};
//计算对象大小的对齐映射规则
// [1,128]					8byte对齐	    freelist[0,16)
// [128+1,1024]				16byte对齐	    freelist[16,72)
// [1024+1,8*1024]			128byte对齐	    freelist[72,128)
// [8*1024+1,64*1024]		1024byte对齐     freelist[128,184)
// [64*1024+1,256*1024]		8*1024byte对齐   freelist[184,208)
class Sizeclass
{
public:
	static inline size_t _roundup(size_t size, size_t arrNum)
	{
		if (size % arrNum != 0&&size>arrNum)
		{
			return (size / arrNum) + 1;
		}
		else if (size % arrNum != 0 && size < arrNum)
		{
			return 1;
		}
		else  if (size % arrNum == 0)
		{
			return size / arrNum;
		}
	}

	static inline size_t roundup(size_t size)
	{
		if (size <= 128)
		{
			return _roundup(size, 8);
		}
		else if (size <= 1024)
		{
			return _roundup(size, 16);
		}
		else if (size <= 8 * 1024)
		{
			return _roundup(size, 128);
		}
		else if (size <= 64 * 1024)
		{
			return _roundup(size, 1024);
		}
		else if (size <= 256 * 1024)
		{
			return _roundup(size, 8 * 1024);
		}
		else
		{
			assert(false);
			return -1;
		}
	}

	static inline size_t  _getindex(size_t size, size_t arrshift)
	{
		size_t arrsize = 1 << arrshift;
		size_t block_count = (size + arrsize - 1) / arrsize;
		return block_count - 1;
	}
	static inline size_t getindex(size_t size)
	{
			assert(size < MAX_Bytes);
			static int ground_num[5] = { 16,52,52,52,24 };
			if (size <= 128)
			{
				return _getindex(size, 3);
			}
			else if (size <= 1024)
			{
				return _getindex(size, 4) + ground_num[0];
			}
			else if (size <= 8 * 1024)
			{
				return _getindex(size, 5) + ground_num[0] + ground_num[1];
			}
			else if (size <= 64 * 1024)
			{
				return _getindex(size, 6)+ground_num[0] + ground_num[1] + ground_num[3];
			}
			else if (size <= 256 * 1024)
			{
				return _getindex(size, 7) + ground_num[0] + ground_num[1] + ground_num[3] + ground_num[4];
			}
			else
			{
				assert(false);
				return -1;
			}

	}

	static size_t getNumFromcentral(size_t size)
	{
		assert(size > 0);
		int num = MAX_Bytes / size;    //动态调整数量避免小对象频繁请求，大对象一次占用过多内存
		if (num < 2)
		{
			num = 2;
		}
		if (num > 512)
		{
			num = 512;
		}
		return num;
	}

	static size_t getNumFrompage(size_t size)
	{
		size_t num = getNumFromcentral(size);
		size_t npage = (num * size) >> PAGE_SHIFT;
		if (npage < 1)
		{
			npage = 1;
		}
		return npage;
	}
};



struct span
{
	PAGE_ID _pageid = 0;  //大内存块页的下标
	size_t  _pagenum = 0;   //页的数量

	span* _next = nullptr;   //双向链表结构
	span* _prev = nullptr;

	size_t _objectsize = 0;  //切好的小内存的大小
	size_t _usenumber = 0; //小内存被threadcache调用的数量
	void* _freelist = nullptr;  //切好的小内存挂载的自由链表

	bool _isUse = false;
};

class Spanlist
{
public:
	 Spanlist()
	{
		 _head = new span;
		 _head->_next = _head;
		 _head->_prev = _head;
	}
	 void* insert(span* pos, span* newspan)
	 {
		 assert(newspan);
		 assert(pos);
		 span* prev = pos->_prev;
		 prev->_next = newspan;
		 newspan->_prev = prev;
		 newspan->_next = pos;
		 pos->_prev = newspan;
	}
	 span* popfront()
	 {
		 span* front = _head->_next;
		 erase(front);
		 return front;

	 }

	 void pushfront(span* newspan)
	 {
		 span* next = _head->_next;
		 _head->_next = newspan;
		 newspan->_prev = newspan;

		 next->_prev = newspan;
		 newspan->_next = next;
	 }
	 void erase(span* pos)
	 {
		 assert(pos);

		 if (pos == _head)
		 {
			 int x = 0;
		 }
		 span* prev = pos->_prev;
		 prev->_next = pos->_next;
	 }
	 bool empty()
	 {
		 return _head->_next;
	 }
	 span* Begin()
	 {
		 return _head->_next;
	 }
	 span* End()
	 {
		 return _head;
	 }
private:
	span* _head;
};